package random;

public class CompactArray2d implements Array2d {
	
	protected long[][][] array;
	protected int size;
	protected static final int SUB = 64;
/*	
	public CompactArray2d(int size) throws IllegalArgumentException{
		if(size%8!=0)
			throw new IllegalArgumentException("Size of array not divisable by 8");
		array = new long[size/8][size/8];
	}

	@Override
	public boolean get(int x, int y) {
		return (array[x/8][y/8] & (1l << (x%8 * 8 + y%8)) ) != 0;
	}

	@Override
	public void set(int x, int y) {
		array[x/8][y/8] |=  (1l << (x%8 * 8 + y%8));
	}

	@Override
	public void unset(int x, int y) {
		array[x/8][y/8] &=  ~(1l << (x%8 * 8 + y%8));
	}
/*/	
	
	private int minX, minY, maxX, maxY;
	
	public CompactArray2d(int size) throws IllegalArgumentException{
		if(size%64!=0 || size%SUB !=0)
			throw new IllegalArgumentException("Size of array not divisable by 64");
		array = new long[size/SUB][][];
		this.size = size;
		minX = size;
		minY = size;
		maxX = 0;
		maxY=0;
	}

	@Override
	public boolean get(int x, int y) {
		if(array[y/SUB] == null)
			return false;
		if(array[y/SUB][x/64] == null)
			return false;
		return (this.getLong(x, y) & (1l << (x%64)) ) != 0;
	}
	
	protected long getLong(int x, int y){
		if(array[y/SUB] == null){
			return 0l;
		}
		if(array[y/SUB][x/64] == null){
			return 0l;
		}
		return array[y/SUB][x/64][y%SUB];
	}

	@Override
	public void set(int x, int y) {
		minX = Math.min(x, minX);
		maxX = Math.max(x, maxX);
		minY = Math.min(y, minY);
		maxY = Math.max(y, maxY);
		this.setLong(x,y,1l << (x%64));
	}
	
	protected void setLong(int x, int y, long l){
		if(array[y/SUB] == null){
			array[y/SUB] = new long[size/64][];
		}
		if(array[y/SUB][x/64] == null){
			array[y/SUB][x/64] = new long[SUB];
		}
		array[y/SUB][x/64][y%SUB] |=l;
	}

	@Override
	public void unset(int x, int y) {
//		if(array[x/64/SUB] == null)
//			return;
//		if(array[x/64/SUB][(x/64)%SUB] == null)
//			return;
//		if(array[x/64/SUB][(x/64)%SUB][y/SUB] == null)
//			return;
//		array[x/64/SUB][(x/64)%SUB][y/SUB][y%SUB] &=  ~(1l << (x%64));
	}
	
	public void print(){
		for (int i = minY; i <= maxY; i++) {
			for (int j = minX; j <= maxX; j++) {
				if (i == size/2 && j == size/2) {
					System.out.print("0");
				}else{
					System.out.print(this.get(j, i) ? "x" : " ");
				}
			}
			System.out.println();
		}
	}
	
	
/**/
}
